package expr

import (
	"fmt"
	"strings"

	"github.com/expr-lang/expr/ast"
	
	"calculator/internal/core/schema"
)

// Dependency 依赖项; 可以依赖当前记录的字段，也可以依赖其他记录或其他表记录的字段
type Dependency struct {
	FieldName string `json:"field_name"`
	TableName string `json:"table_name"`
}

// DependencyVisitor 表达式依赖收集器，实现Visitor接口
type DependencyVisitor struct {
	Dependencies []Dependency // 收集到的依赖项列表
	currentTable string       // 当前表名，用于设置默认TableName
	schema       *schema.Schema // Schema实例，用于查询字段信息
}

// NewDependencyVisitor 创建新的依赖收集器实例
func NewDependencyVisitor() *DependencyVisitor {
	return &DependencyVisitor{
		Dependencies: make([]Dependency, 0),
	}
}

// WithCurrentTable 设置当前表名
func (v *DependencyVisitor) WithCurrentTable(tableName string) *DependencyVisitor {
	v.currentTable = tableName
	return v
}

// WithSchema 设置Schema实例
func (v *DependencyVisitor) WithSchema(schema *schema.Schema) *DependencyVisitor {
	v.schema = schema
	return v
}

// Visit 实现Visitor接口的Visit方法，用于遍历表达式节点
func (v *DependencyVisitor) Visit(node *ast.Node) {
	if *node == nil {
		return
	}
	// 根据节点类型进行不同处理
	switch n := (*node).(type) {
	case *ast.IdentifierNode:
		// 标识符节点，通常是字段名
		v.handleIdentifier(n.Value)
	
	case *ast.CallNode:
		// 函数调用节点，需要分析参数中的依赖
		v.handleFunctionCall(n)
	
	case *ast.MemberNode:
		// 成员访问节点，如 record.field
		v.handleMemberAccess(n)
	
	case *ast.BuiltinNode:
		// 内置函数节点
		v.handleBuiltinFunction(n)
	}
}

// handleIdentifier 处理标识符节点
func (v *DependencyVisitor) handleIdentifier(fieldName string) {
	// 跳过空字段名
	if fieldName == "" {
		return
	}
	
	// 跳过常见的关键字和内置函数名
	if isReservedWord(fieldName) {
		return
	}
	
	// 自动推断表名
	tableName := v.inferTableName(fieldName)
	
	// 添加依赖项
	v.Dependencies = append(v.Dependencies, Dependency{
		FieldName: fieldName,
		TableName: tableName,
	})
}

// handleFunctionCall 处理函数调用节点
func (v *DependencyVisitor) handleFunctionCall(callNode *ast.CallNode) {
	// 获取函数名
	var functionName string
	switch fn := callNode.Callee.(type) {
	case *ast.IdentifierNode:
		functionName = fn.Value
	case *ast.MemberNode:
		// 处理成员函数调用，如 table.field()
		if ident, ok := fn.Property.(*ast.IdentifierNode); ok {
			functionName = ident.Value
		}
	}
	
	// 根据函数名处理不同的依赖关系
	switch functionName {
	case "cur":
		// cur() 函数依赖当前记录的所有字段
		v.handleCurFunction()
		
	case "index", "record", "records":
		// 索引查询函数，分析表名和索引字段
		v.handleIndexFunction(callNode, functionName)
		
	case "field":
		// field() 函数，分析记录和字段名
		v.handleFieldFunction(callNode)
		
	case "expr", "exprs":
		// 嵌套表达式函数，需要递归分析
		v.handleExprFunction(callNode)
		
	default:
		// 其他函数，分析参数中的依赖
		v.analyzeArguments(callNode.Arguments)
	}
}

// handleMemberAccess 处理成员访问节点
func (v *DependencyVisitor) handleMemberAccess(memberNode *ast.MemberNode) {
	// 处理 record.field 形式的访问
	if ident, ok := memberNode.Property.(*ast.IdentifierNode); ok {
		// 这里可以进一步分析对象部分，但目前简单处理为字段依赖
		v.handleIdentifier(ident.Value)
	}
}

// handleBuiltinFunction 处理内置函数节点
func (v *DependencyVisitor) handleBuiltinFunction(builtinNode *ast.BuiltinNode) {
	// 内置函数通常不产生字段依赖，但可能需要分析参数
	// 这里可以根据具体的内置函数进行特殊处理
}

// handleCurFunction 处理 cur() 函数
func (v *DependencyVisitor) handleCurFunction() {
	// cur() 函数表示依赖当前记录的所有字段
	// 这里可以返回特殊标记，或者在实际使用中动态分析
	// 目前简单处理为不添加具体依赖，由调用方处理
}

// handleIndexFunction 处理索引查询函数
func (v *DependencyVisitor) handleIndexFunction(callNode *ast.CallNode, functionName string) {
	if len(callNode.Arguments) < 2 {
		return
	}
	
	// 第一个参数通常是表名
	if tableNameNode, ok := callNode.Arguments[0].(*ast.StringNode); ok {
		tableName := tableNameNode.Value
		
		// 第二个参数通常是索引字段名
		if indexFieldNode, ok := callNode.Arguments[1].(*ast.StringNode); ok {
			indexField := indexFieldNode.Value
			
			// 添加索引字段依赖
			v.Dependencies = append(v.Dependencies, Dependency{
				FieldName: indexField,
				TableName: tableName,
			})
		}
		
		// 如果有第三个参数，可能是索引值（可能包含表达式）
		if len(callNode.Arguments) > 2 {
			// 递归分析表达式参数，保持原来的当前表名
			nestedVisitor := NewDependencyVisitor().
				WithCurrentTable(v.currentTable).
				WithSchema(v.schema)
			ast.Walk(&callNode.Arguments[2], nestedVisitor)
			v.Dependencies = append(v.Dependencies, nestedVisitor.Dependencies...)
		}
	}
}

// handleFieldFunction 处理 field() 函数
func (v *DependencyVisitor) handleFieldFunction(callNode *ast.CallNode) {
	if len(callNode.Arguments) < 2 {
		return
	}
	
	// 第二个参数是字段名
	if fieldNameNode, ok := callNode.Arguments[1].(*ast.StringNode); ok {
		fieldName := fieldNameNode.Value
		
		// 第一个参数是记录（可能包含表信息）
		// 这里可以进一步分析记录来源
		v.handleIdentifier(fieldName)
	}
}

// handleExprFunction 处理 expr() 函数
func (v *DependencyVisitor) handleExprFunction(callNode *ast.CallNode) {
	if len(callNode.Arguments) < 2 {
		return
	}
	
	// 第二个参数是表达式字符串
	if exprNode, ok := callNode.Arguments[1].(*ast.StringNode); ok {
		_ = exprNode.Value // 暂时不使用，后续可以用于嵌套表达式分析
		
		// 递归分析嵌套表达式
		// 这里需要创建新的解析器实例来分析嵌套表达式
		// 目前简单处理为不分析嵌套表达式
	}
}

// inferTableName 自动推断字段所属的表名
func (v *DependencyVisitor) inferTableName(fieldName string) string {
	// 如果提供了Schema实例，尝试自动推断表名
	if v.schema != nil {
		// 首先检查当前表是否包含该字段
		if v.currentTable != "" && v.schema.HasField(v.currentTable, fieldName) {
			return v.currentTable
		}
		
		// 在整个Schema中查找字段
		if _, tableName, err := v.schema.FindField(fieldName); err == nil {
			return tableName
		}
	}
	
	// 如果无法自动推断，使用当前表名作为默认值
	return v.currentTable
}

// analyzeArguments 分析函数参数中的依赖
func (v *DependencyVisitor) analyzeArguments(arguments []ast.Node) {
	for _, arg := range arguments {
		// 对每个参数递归分析依赖
		nestedVisitor := NewDependencyVisitor().
			WithCurrentTable(v.currentTable).
			WithSchema(v.schema)
		ast.Walk(&arg, nestedVisitor)
		v.Dependencies = append(v.Dependencies, nestedVisitor.Dependencies...)
	}
}

// isReservedWord 判断是否为保留字
func isReservedWord(word string) bool {
	reservedWords := []string{
		"true", "false", "null", "nil",
		"cur", "index", "record", "records", "field", "expr", "exprs",
		"if", "else", "for", "while", "return", "func",
	}
	
	for _, reserved := range reservedWords {
		if strings.EqualFold(word, reserved) {
			return true
		}
	}
	return false
}

// GetDependencies 获取去重后的依赖项列表
func (v *DependencyVisitor) GetDependencies() []Dependency {
	return v.removeDuplicates(v.Dependencies)
}

// removeDuplicates 去除重复的依赖项
func (v *DependencyVisitor) removeDuplicates(dependencies []Dependency) []Dependency {
	seen := make(map[string]bool)
	result := make([]Dependency, 0)
	
	for _, dep := range dependencies {
		key := fmt.Sprintf("%s.%s", dep.TableName, dep.FieldName)
		if !seen[key] && dep.FieldName != "" {
			seen[key] = true
			result = append(result, dep)
		}
	}
	
	return result
}